package com.yxw.live_vod_boot.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.shaded.com.google.common.base.Joiner;
import com.volcengine.helper.VodUploadMediaProcessListener;
import com.volcengine.helper.VodUploadProgressListener;
import com.volcengine.model.beans.Functions;
import com.volcengine.service.vod.Const;
import com.volcengine.service.vod.IVodService;
import com.volcengine.service.vod.impl.VodServiceImpl;
import com.volcengine.service.vod.model.business.*;
import com.volcengine.service.vod.model.request.*;
import com.volcengine.service.vod.model.response.*;
import com.yxw.live_vod_boot.dto.UploadVideoToHsDTO;
import com.yxw.live_vod_boot.enums.HsSdkEnum;
import com.yxw.live_vod_boot.vo.HsSourceMaterialVo;
import com.yxw.live_vod_boot.vo.HsVideoReviewVo;
import com.yxw.live_vod_boot.vo.VolcanoVideoInfoVO;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 火山引擎操作工具类
 * liuxin
 * 2023.11.15
 */
@Component
@Slf4j
public class VolcanoEngineUtil {

    //火山引擎账号密钥ID
    @Value("${volcano.access_key_id:AKLTZGYxOWU3MGQyNTM2NDMyNTgzODExNjRhZTU1NDlmODk}")
    private String accessKeyId;

    //火山引擎账号密钥key
    @Value("${volcano.secret_access_key:TVdZMlptSTBaV0ZoTmpjMk5EUmxNemxoWkRjM1lqSTVOVFJtWTJWaE1XUQ==}")
    private String secretAccessKey;

    @Value("${volcano.video.space:yingxi-video}")
    private String videoSpace;

    @Autowired
    private ApplicationContext applicationContext;



    /**
     * 上传视频(媒资上传)
     * 本地文件绝对路径
     */
    public HsVideoReviewVo uploadVideoToHs(UploadVideoToHsDTO videoToHsDTO) {
        //下载到本地
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        List<Functions> functionsList = new ArrayList<>();
        Functions getMetaFunc = Functions.GetMetaFunction();
        functionsList.add(getMetaFunc);
        Functions snapShotFunc = Functions.SnapShotFunction(2.3);
        functionsList.add(snapShotFunc);
        VodUploadMediaRequest vodUploadMediaRequest = VodUploadMediaRequest.newBuilder()
                .setSpaceName(videoSpace)
                .setFilePath("D:\\软件安装\\ev\\录制目录\\桌面视频.mp4")
                .setFileName(videoToHsDTO.getFileName())
                .setFunctions(JSON.toJSONString(functionsList))
                .setStorageClass(0)
                //            .setUploadStrategy(1)  低内存模式，对内存需求较高进行设置，传值为 1。无内存需求不需要特别设置
                .build();
        // 需要进度条功能时添加相应 listener，如无需求，传 null 值即可
        VodUploadProgressListener listener = new VodUploadMediaProcessListener();
        HsVideoReviewVo vo = new HsVideoReviewVo();
        try {
            VodCommitUploadInfoResponse vodCommitUploadInfoResponse = vodService.uploadMedia(vodUploadMediaRequest, listener);
            if (vodCommitUploadInfoResponse.getResponseMetadata().hasError()) {
                throw new BaseException(vodCommitUploadInfoResponse.getResponseMetadata().getError() + "");
            }
            log.info(vodCommitUploadInfoResponse.toString());
            String vid = vodCommitUploadInfoResponse.getResult().getData().getVid();
            //发布视频
            this.publishStatus(vid,videoToHsDTO.getExamineId());
            vo.setPlayUrl(this.getPlayInfo(vid,videoToHsDTO.getExamineId()).getPlayUrl());
            log.info(vid);
            vo.setVid(vid);
            log.info(vodCommitUploadInfoResponse.getResponseMetadata().getRequestId());
        } catch (Exception e) {
            log.error("上传视频失败：" + e.getMessage());
            throw new BaseException("上传视频失败：" + e.getMessage());
        }
        return vo;
    }

    /**
     * 图片上传素材
     * 本地文件绝对路径
     *
     * @param videoToHsDTO
     */
    public HsSourceMaterialVo uploadSourceMaterialToHs(UploadVideoToHsDTO videoToHsDTO) {
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        List<Functions> functionsList = new ArrayList<>();
        Functions getMetaFunc = Functions.GetMetaFunction();
        functionsList.add(getMetaFunc);
        Functions snapShotFunc = Functions.SnapShotFunction(2.3);
        functionsList.add(snapShotFunc);
        Functions addOptionInfo = Functions.AddOptionInfoFunction("封面图片上传素材", "test", "图片文件", Const.CategoryImage, "jpg");
        functionsList.add(addOptionInfo);
        VodUploadMaterialRequest vodUploadMaterialRequest = VodUploadMaterialRequest.newBuilder()
                .setSpaceName(videoSpace)
                .setFilePath("D:\\软件安装\\ev\\录制目录\\封面.jpg")
                .setFileName(videoToHsDTO.getFileName())
                .setFileType(Const.FileTypeImage)
                .setFunctions(JSON.toJSONString(functionsList))
                .build();
        HsSourceMaterialVo vo = new HsSourceMaterialVo();
        try {
            VodCommitUploadInfoResponse vodCommitUploadInfoResponse = vodService.uploadMaterial(vodUploadMaterialRequest, null);
            if (vodCommitUploadInfoResponse.getResponseMetadata().hasError()) {
                throw new BaseException(vodCommitUploadInfoResponse.getResponseMetadata().getError() + "");
            }
            log.info(vodCommitUploadInfoResponse.toString());
            String mid = vodCommitUploadInfoResponse.getResult().getData().getMid();
            log.info(mid);
            vo.setMid(mid);
            log.info(vodCommitUploadInfoResponse.getResponseMetadata().getRequestId());
        } catch (Exception e) {
            log.error("上传素材失败：" + e.getMessage());
            throw new BaseException("上传素材失败：" + e.getMessage());
        }
        return vo;
    }


    /**
     * 1：URL批量拉取上传
     * 华为云下载路径
     * @param videoToHsDTO
     */
    public String uploadMediaByUrl(UploadVideoToHsDTO videoToHsDTO) {
        try {
            com.volcengine.service.vod.model.request.VodUrlUploadRequest.Builder reqBuilder = com.volcengine.service.vod.model.request.VodUrlUploadRequest.newBuilder();
            //视频空间
            reqBuilder.setSpaceName(videoSpace);
            com.volcengine.service.vod.model.business.VodUrlUploadURLSet.Builder uRLSetsBuilder = com.volcengine.service.vod.model.business.VodUrlUploadURLSet.newBuilder();
            //源视频URL（华为云下载地址）
            uRLSetsBuilder.setSourceUrl(videoToHsDTO.getLocalfileUrl());
            //1：标准存储。2：归档存储。3：低频存储。
            uRLSetsBuilder.setStorageClass(1);
            //视频名称
            uRLSetsBuilder.setTitle(videoToHsDTO.getFileName());
            //格视频格式后缀
            uRLSetsBuilder.setFileExtension(videoToHsDTO.getFileName().substring(videoToHsDTO.getFileName().lastIndexOf("."), videoToHsDTO.getFileName().length()));
            reqBuilder.addURLSets(uRLSetsBuilder);
            //获取代理对象，不然AOP切面获取不到
            VolcanoEngineUtil volcanoEngineUtil = applicationContext.getBean(VolcanoEngineUtil.class);
            VodUrlUploadResponse resp= (VodUrlUploadResponse)(volcanoEngineUtil.callVideolSdk(reqBuilder,HsSdkEnum.UPLOAD_MEDIA_BY_URL,videoToHsDTO.getExamineId()));
            if (resp.getResponseMetadata().hasError()) {
                throw new BaseException(resp.getResponseMetadata().getError() + "");
            }
            log.error("URL上传结果=============================》" + resp);
            String  jobId= "";
            //解析上传地址,获取jobId来查询上传的url和vid
            VodUrlResponseData result = resp.getResult();
            if (null != result) {
                List<ValuePair> dataList = result.getDataList();
                if (null != dataList && !dataList.isEmpty()){
                    jobId= dataList.get(0).getJobId();
                }
            }
            if (StringUtils.isBlank(jobId)) {
                throw new BaseException("上传返回数据异常,请联系管理员处理");
            }
            return jobId;
        } catch (Exception e) {
            log.error("URL上传视频出错：" + e.getMessage());
            throw new BaseException("URL上传视频出错：" + e.getMessage());
        }
    }

    /**
     * 2：查询URL批量上传任务状态
     */
    public String queryUploadTaskInfo(String jobId,Long bussId) {
        HsVideoReviewVo vo = new HsVideoReviewVo();
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        try {
            //延时查询
            Thread.sleep(3000);
            List<String> jobIds = Arrays.asList(jobId);
            VodQueryUploadTaskInfoRequest vodQueryUploadTaskInfoRequest = VodQueryUploadTaskInfoRequest.newBuilder()
                    .setJobIds(String.join(",", jobIds))
                    .build();
            //获取代理对象，不然AOP切面获取不到
            VolcanoEngineUtil volcanoEngineUtil = applicationContext.getBean(VolcanoEngineUtil.class);
            VodQueryUploadTaskInfoResponse resp=(VodQueryUploadTaskInfoResponse)volcanoEngineUtil.callVideolSdk(vodQueryUploadTaskInfoRequest,HsSdkEnum.QUERY_UPLOAD_TASK_INFO,bussId);
            if (resp.getResponseMetadata().hasError()) {
                throw new BaseException(resp.getResponseMetadata().getError() + "");
            }
            log.error("URL批量上传任务状态返回=============================》" + resp);
            VodQueryData result = resp.getResult();
            String vid="";
            if(null!=result){
                VodQueryUploadResult data = result.getData();
                if(null!=data){
                    List<VodURLSet> mediaInfoListList = data.getMediaInfoListList();
                    if(null!=mediaInfoListList && !mediaInfoListList.isEmpty()){
                        VodURLSet vodInfo = mediaInfoListList.get(0);
                        String state = vodInfo.getState();
                        if("success".equals(state)){
                            vid=vodInfo.getVid();
                        }else if("fail".equals(state)){
                            throw new BaseException("上传视频返回出错,请联系管理员");
                        }
                    }
                }
            }
            return vid;
        } catch (Exception e) {
            log.error("URL批量上传任务状态返回：" + e.getMessage());
            throw new BaseException("URL批量上传任务状态返回：" + e.getMessage());
        }
    }

    /**
     * 3：修改媒资发布状态
     */
    public void publishStatus(String vid,Long bussId) {
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        try {
            VodUpdateMediaPublishStatusRequest.Builder req = VodUpdateMediaPublishStatusRequest.newBuilder();
            req.setVid(vid);
            req.setStatus("Published");
            //获取代理对象，不然AOP切面获取不到
            VolcanoEngineUtil volcanoEngineUtil = applicationContext.getBean(VolcanoEngineUtil.class);
            VodUpdateMediaPublishStatusResponse resp =  (VodUpdateMediaPublishStatusResponse)(volcanoEngineUtil.callVideolSdk(req,HsSdkEnum.UPDATE_MEDIA_PUBLISH_STATUS,bussId));
            if (resp.getResponseMetadata().hasError()) {
                throw new BaseException(resp.getResponseMetadata().getError() + "");
            }
            log.info("媒资发布返回参数=========================》" + resp);
        } catch (Exception e) {
            log.error("媒资发布失败：" + e.getMessage());
            throw new BaseException("媒资发布失败：" + e.getMessage());
        }
    }

    /**
     * 4：查询播放地址
     */
    public VolcanoVideoInfoVO getPlayInfo(String vid,Long bussId) {
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        VolcanoVideoInfoVO vo = new VolcanoVideoInfoVO();
        try {
            com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.Builder reqBuilder = com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.newBuilder();
            reqBuilder.setVid(vid);
            //https播放地址
            reqBuilder.setSsl("1");
            //获取代理对象，不然AOP切面获取不到
            VolcanoEngineUtil volcanoEngineUtil = applicationContext.getBean(VolcanoEngineUtil.class);
            com.volcengine.service.vod.model.response.VodGetPlayInfoResponse resp =  (VodGetPlayInfoResponse)(volcanoEngineUtil.callVideolSdk(reqBuilder,HsSdkEnum.GET_PLAY_INFO,bussId));
            if (resp.getResponseMetadata().hasError()) {
                throw new BaseException(resp.getResponseMetadata().getError() + "");
            }
            log.info("播放地址返回参数=========================》" + resp);
            //解析返回参数
            //解析返回参数
            VodPlayInfoModel result = resp.getResult();
            if (null != result) {
                List<VodPlayInfo> playInfoListList = result.getPlayInfoListList();
                if (null != playInfoListList && !playInfoListList.isEmpty()) {
                    VodPlayInfo playInfoList = result.getPlayInfoList(0);
                    if (null != playInfoList) {
                        String playUrl = playInfoList.getMainPlayUrl();
                        Float duration = playInfoList.getDuration();
                        vo.setPlayUrl(playUrl);
                        vo.setDuration(duration);
                    }
                }
            }
            if (StringUtils.isBlank(vo.getPlayUrl())) {
                throw new BaseException("未获取到播放地址");
            }
            log.info("播放地址=====================》" + vo.getPlayUrl());
            return vo;
        } catch (Exception e) {
            log.error("查询播放地址失败：" + e.getMessage());
            throw new BaseException("查询播放地址失败：" + e.getMessage());
        }
    }

    /**
     * 批量删除完整媒资
     * @param vidList
     */
    public void deleteMedia(List<String> vidList,Long bussId) {
        try {
            //视频 Vid 列表。多个 Vid 以","隔开。单次最多支持 20个
            Integer size=vidList.size();
            Integer num=size%20==0?size/20:size/20+1;
            for (int i = 0; i <num; i++) {
                String vids =Joiner.on(",").join(vidList.stream().skip(i* 20).limit((20)).collect(Collectors.toList()));
                String callBackArgs = "CallBackArgs";
                VodDeleteMediaRequest.Builder req = VodDeleteMediaRequest.newBuilder();
                req.setVids(vids);
                req.setCallbackArgs(callBackArgs);
                //获取代理对象，不然AOP切面获取不到
                VolcanoEngineUtil volcanoEngineUtil = applicationContext.getBean(VolcanoEngineUtil.class);
                VodDeleteMediaResponse resp =  (VodDeleteMediaResponse)(volcanoEngineUtil.callVideolSdk(req,HsSdkEnum.DELETE_MEDIA,bussId));
                if (resp.getResponseMetadata().hasError()) {
                    throw new BaseException(resp.getResponseMetadata().getError() + "");
                }
                log.error("批量删除完整媒资失败：========================》" +resp);
            }
        } catch (Exception e) {
            log.error("批量删除完整媒资失败：" + e.getMessage());
            throw new BaseException("批量删除完整媒资失败：" + e.getMessage());
        }
    }


    //-------------------------------------------------------------------------------------------------------------------------------------------------
    /**
     * 调用sdk单独写方法，方便aop保存日志
     * obj:sdk入参
     * sdkEnum: sdk调用信息
     * bussId：审核视频ID
     */
    public Object callVideolSdk(Object obj, HsSdkEnum sdkEnum,Long bussId) throws Exception {
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey(accessKeyId);
        vodService.setSecretKey(secretAccessKey);
        if(1==sdkEnum.getCode()){
            VodUrlUploadRequest.Builder builder = (VodUrlUploadRequest.Builder) obj;
            return  vodService.uploadMediaByUrl(builder.build());
        }else if(2==sdkEnum.getCode()){
            VodQueryUploadTaskInfoRequest request = (VodQueryUploadTaskInfoRequest) obj;
            return  vodService.queryUploadTaskInfo(request);
        }else if(3==sdkEnum.getCode()){
            VodUpdateMediaPublishStatusRequest.Builder builder = (VodUpdateMediaPublishStatusRequest.Builder) obj;
            return  vodService.updateMediaPublishStatus(builder.build());
        }else if(4==sdkEnum.getCode()){
             VodGetPlayInfoRequest.Builder  builder = (VodGetPlayInfoRequest.Builder) obj;
            return  vodService.getPlayInfo(builder.build());
        } else if(5==sdkEnum.getCode()){
            VodDeleteMediaRequest.Builder  builder = (VodDeleteMediaRequest.Builder) obj;
            return  vodService.deleteMedia(builder.build());
        }
        return null;
    }

    public static void main(String[] args) {
        IVodService vodService = VodServiceImpl.getInstance();
        vodService.setAccessKey("AKLTZGYxOWU3MGQyNTM2NDMyNTgzODExNjRhZTU1NDlmODk");
        vodService.setSecretKey("TVdZMlptSTBaV0ZoTmpjMk5EUmxNemxoWkRjM1lqSTVOVFJtWTJWaE1XUQ==");
        VolcanoVideoInfoVO vo = new VolcanoVideoInfoVO();
        try {
            com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.Builder reqBuilder = com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.newBuilder();
            reqBuilder.setVid("v02b1fg10003cm5a86hs1v0qffjh0cj0");
            reqBuilder.setSsl("0");
            //获取代理对象，不然AOP切面获取不到
//            com.volcengine.service.vod.model.response.VodGetPlayInfoResponse resp = (VodGetPlayInfoResponse) (volcanoEngineUtil.callVideolSdk(reqBuilder, HsSdkEnum.GET_PLAY_INFO, bussId));            com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.Builder reqBuilder = com.volcengine.service.vod.model.request.VodGetPlayInfoRequest.newBuilder();
            com.volcengine.service.vod.model.response.VodGetPlayInfoResponse resp = vodService.getPlayInfo(reqBuilder.build());
            if (resp.getResponseMetadata().hasError()) {
                throw new BaseException(resp.getResponseMetadata().getError() + "");
            }
            log.info("播放地址返回参数=========================》" + resp);
            //解析返回参数
            //解析返回参数
            VodPlayInfoModel result = resp.getResult();
            if (null != result) {
                List<VodPlayInfo> playInfoListList = result.getPlayInfoListList();
                if (null != playInfoListList && !playInfoListList.isEmpty()) {
                    VodPlayInfo playInfoList = result.getPlayInfoList(0);
                    if (null != playInfoList) {
                        String playUrl = playInfoList.getMainPlayUrl();
                        Float duration = playInfoList.getDuration();
                        vo.setPlayUrl(playUrl);
                        vo.setDuration(duration);
                    }
                }
            }
            if (StringUtils.isBlank(vo.getPlayUrl())) {
                throw new BaseException("未获取到播放地址");
            }
            log.info("播放地址=====================》" + vo.getPlayUrl());
        } catch (Exception e) {
            log.error("查询播放地址失败：" + e.getMessage());
            throw new BaseException("查询播放地址失败：" + e.getMessage());
        }
    }
}
